const jwt = require('jsonwebtoken');
const md5 = require('js-md5')
const fs = require('node:fs');
const path = require('node:path');
var session = require('express-session');
const { accToUesrNameSelectUser } = require('../users/search');
const { 
  getTokenExpirationTime,
  getTokenMaxAge,
  tokenIDCache
 } =require('../../utils/otherUtils/other')

// 变量
let PRIVATE_KEY = null
let PUBLIC_KEY = null
const TOKEN_EXPRESIN =  getTokenExpirationTime()
const NODE_CACHE_KEY = 'is_new_old_token'

if(process.env.NODE_ENV === 'production') {
  PRIVATE_KEY =   path.resolve(__dirname,'keyOpenSSL/private.key')
  PUBLIC_KEY = path.resolve(__dirname,'keyOpenSSL/public.key')
}else if ( process.env.NODE_ENV === 'development' ){
  PRIVATE_KEY = path.resolve(__dirname,'../../keyOpenSSL/private.key')
  PUBLIC_KEY = path.resolve(__dirname,'../../keyOpenSSL/public.key')
}



const privateKey = fs.readFileSync(PRIVATE_KEY); // 私钥
const publicKey = fs.readFileSync(PUBLIC_KEY); // 公钥

const MAXAGE = getTokenMaxAge() // 最大更新时间（秒）

// 从数据库中获取用户名
async function getUserName(userName) {
  try {
    
    return rows
  }
  catch(err) {
    return {
      error: err,
      msg: '获取注册用户信息失败'
    }
  }
}


// 生成token 并 存储在 session 中
const createToken = function (req, res,payLoad) {

    const token = jwt.sign(payLoad, privateKey, {
      // expiresIn: 1000 * 60 *5,
      algorithm: 'RS256' 
    })
    // 存储

    tokenIDCache.set({
      key: NODE_CACHE_KEY,
      val: (payLoad.iat || 0), 
      ttl: getTokenExpirationTime()
    })
  req.session.createTokenTime = payLoad.iat || 0
    return token
}


const jwtAuth = async function(req, res, next) {
  try {
    const { username, password, verifyCode} = req.body;
    const userName = username
    const rows  = await accToUesrNameSelectUser({
      userName,
      connection: req.connection
    })

    if( !rows || Array.isArray(rows) && rows.length === 0 ) {
      return res.resend.sendJson(req,res, {
        status: 400,
        code: 'FAIL',
        data: '',
        msg: '注册用户不存在'
      })
    }
  const { userName: USERNAME, passWord:passwordMd5 } = rows[0]
  // 留存密码进行解析MD5
  // const passwordMd5 = md5(PASSWORD)

  if( !username || !password || !verifyCode) {
    // res.log.error('缺少参数')
    res.resend.sendJson(req,res, {
      status: 400,
      code: 'FAIL',
      data: '',
      msg: '缺少参数'
    })
    return
  }
  if ( username !== USERNAME) {
    // res.log.error('用户名错误')
    res.resend.sendJson(req,res, {
      status: 400,
      code: 'FAIL',
      data: '',
      msg: '用户名错误'
    })
    return
  } else if( username === USERNAME && password !== passwordMd5) {
    // res.log.error('密码错误')
    res.resend.sendJson(req, res, {
      status: 400,
      code: 'FAIL',
      data: '',
      msg: '密码错误'
    })
    return
  } else if( !req.session.captchaCode) {
    res.resend.sendJson(req, res, {
      status: 400,
      code: 'FAIL',
      data: '',
      msg: '验证码失效'
    })
    return
  } else if( username === USERNAME && password === passwordMd5 && verifyCode.toLowerCase() !== req.session.captchaCode) {
    res.resend.sendJson(req, res, {
      status: 400,
      code: 'FAIL',
      data: '',
      msg: '验证码错误'
    })
    return
  }

  const payload = {
      iat: Math.floor(Date.now() / 1000), // 签发时间
      exp: Math.floor(Date.now() / 1000) + TOKEN_EXPRESIN, // 12小时
      username
    }

  const token =  createToken(req, res, payload)
  
  res.resend.sendJson(req, res, {
    status: 200,
    code: 'SUCCESS',
    data: {
      token
    },
    msg: '登入成功'
  })
  }
  catch(err) {  
    res.resend.sendJson(req, res, {
      status: 500,
      code: 'FAIL',
      data: '',
      msg: err.message,
      logMsg: err
    })
  }
}


/**
 * Checks if the token is still valid based on its age.
 *
 * @param {Object} params - The parameters containing token information.
 * @param {number} params.exp - The expiration time of the token.
 * @param {number} params.iat - The issued at time of the token.
 * @param {number} maxAge - The maximum allowed age for the token.
 * @returns {boolean} - Returns true if the token is within the valid age, otherwise false.
 */
function  tokenedReset(params, maxAge) {
  const { exp, iat } = params
  if(!exp) {
    return false
  }
  const vAge =  exp  - Math.floor(Date.now() / 1000)
  
  if( vAge < maxAge) return true
  return false
}



// JWT 处理函数
exports.postUserLogin = function(req, res, next) {
  jwtAuth(req, res, next)
}

// jWT 验证中间件
exports.verifyToken = function(req, res, next) {
  const tokenT = req.headers.authorization;
  const token = tokenT ? tokenT.split(' ')[1] : ''

  if(!token) {
    // res.log.info('缺少 token')
    return res.resend.sendJson(req, res, {
      status: 401,
      code: 'FAIL',
      data: '',
      msg: '缺少 token'
    })
  }  
  jwt.verify(token, publicKey, { algorithms: [ 'HS256','RS256']}, function(err, payload) {

    if(err || !payload) {
      // res.log.info('token 失效')
      return res.resend.sendJson(req, res,{
        status: 403,
        code: 'FAIL',
        data: '',
        msg: 'toen 失效',
        logMsg: err
      })
    }
    req.payLoad = payload
    next()
  })
}

// 验证token是否是旧token
exports.verifyOldToken = function(req, res, next) {
   const { iat } = req.payLoad;
   if( !iat ) {
    return res.resend.sendJson(req, res, {
      status: 403,
      code: 'FAIL',
      data: '',
      msg: '旧token无效',
      logMsg: {
        message: 'token标志不存在，token无效',
      }
    })
   }
   const oldToken = tokenIDCache.get(NODE_CACHE_KEY)[NODE_CACHE_KEY]
   const isOldToken =  iat === oldToken
   if( !isOldToken) {
    return res.resend.sendJson(req, res, {
      status: 403,
      code: 'FAIL',
      data: '',
      msg: '旧token无效',
      logMsg: {
        message: 'token标志不相等，token无效', 
      }
    })
   }
   next()
}

/**
 * 验证载荷(userName)是否正确
*/

exports.verifyPayload = function(req, res, next) {
  // console.log(req.payLoad.username, 'userName')
  
    const userName = req.payLoad.username || ''
    accToUesrNameSelectUser({
      userName,
      connection: req.connection
    }).then((rows) => {
     
      if( !rows || Array.isArray(rows) && rows.length === 0 ) {
        return res.resend.sendJson(req, res, {
          status: 403,
          code: 'FAIL',
          data: '',
          msg: '注册用户不存在,token校验失败'
        })
      }
      next()
    }).catch( (error) => {
      return res.resend.sendJson(req, res, {
        status: 500,
        code: 'FAIl',
        data: '',
        msg: error.message,
        logMsg: error        
      })
    })
  
}

// 是否生成 新token
exports.isCreateNewToken = function (req,res,next) {
  const payload = req.payLoad
  const setTokenLog = tokenedReset(payload, MAXAGE)

  if(setTokenLog) {
    const payloadCon = {
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + TOKEN_EXPRESIN,
       // 12小时
      username: payload.username
    }
    const newToken = createToken(req, res, payloadCon)
    
    req.newToken = newToken
    return next()
  }
  next()
}


// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzExMTUsImV4cCI6MTc0MDYzMTQxNSwidXNlcm5hbWUiOiJhZG1pbiJ9.IUWobk2s6M8zlyTKKaordQYnAolNJbi0sH3nNJwHTFc8zYENwyzEkuUTbuB_K0Ng8BLyL_iDCZDp5MjGdFDtgyadc7B0mWCQeF0_MOunhMXFghwGVyKydnwAxF1K0-b0MfC1LFq23li7N9o2fgZI9fJguTwBBO03cjGQiKFQ3hoSvenkjTQDNkcxPKO3irBChiSou6bfSVxs7WYpqcaGe9yMr3giVQz3Ey1KgFgCHWDcOmgbGInwlBFnTCyk0eeOYMtM3fdvc-cSQXxoj4df7IN6Jrqpviwtzp-uHE1c2KHjkYIqtT5_xrXqNXWizs6vceYOlx_wUwnRaMS_oXmyaA


// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzExMTUsImV4cCI6MTc0MDYzMTQxNSwidXNlcm5hbWUiOiJhZG1pbiJ9.IUWobk2s6M8zlyTKKaordQYnAolNJbi0sH3nNJwHTFc8zYENwyzEkuUTbuB_K0Ng8BLyL_iDCZDp5MjGdFDtgyadc7B0mWCQeF0_MOunhMXFghwGVyKydnwAxF1K0-b0MfC1LFq23li7N9o2fgZI9fJguTwBBO03cjGQiKFQ3hoSvenkjTQDNkcxPKO3irBChiSou6bfSVxs7WYpqcaGe9yMr3giVQz3Ey1KgFgCHWDcOmgbGInwlBFnTCyk0eeOYMtM3fdvc-cSQXxoj4df7IN6Jrqpviwtzp-uHE1c2KHjkYIqtT5_xrXqNXWizs6vceYOlx_wUwnRaMS_oXmyaA

// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzExMTUsImV4cCI6MTc0MDYzMTQxNSwidXNlcm5hbWUiOiJhZG1pbiJ9.IUWobk2s6M8zlyTKKaordQYnAolNJbi0sH3nNJwHTFc8zYENwyzEkuUTbuB_K0Ng8BLyL_iDCZDp5MjGdFDtgyadc7B0mWCQeF0_MOunhMXFghwGVyKydnwAxF1K0-b0MfC1LFq23li7N9o2fgZI9fJguTwBBO03cjGQiKFQ3hoSvenkjTQDNkcxPKO3irBChiSou6bfSVxs7WYpqcaGe9yMr3giVQz3Ey1KgFgCHWDcOmgbGInwlBFnTCyk0eeOYMtM3fdvc-cSQXxoj4df7IN6Jrqpviwtzp-uHE1c2KHjkYIqtT5_xrXqNXWizs6vceYOlx_wUwnRaMS_oXmyaA


// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzE2MzYsImV4cCI6MTc0MDYzMTkzNiwidXNlcm5hbWUiOiJhZG1pbiJ9.NF5QP6X9lxTU762hs6stWWQ2EsxVKxGQK1Y9LSaHdxrVKdvaFqc2pGyTrVf5RELXsfEc_u6bJR4_QXAHw9zMnXf-v1igly_fI3Nwr1l5iRHdHYPTxKZvfXl3jW6bwU1julX-LhkvrWNDYuGkECOIiiNomWbfqbef7inXxHYfD4-rR0mG_P80GF012RQLUWyAGqt2tf1ZiHQvKqbwIsuAar_lpGz6QWe4F4M1Vk8snlVwyu-Xk-H910n6ytaIOE-_RHSwuOr-gu--kJns9ZfPMoUgDCQO4rm9z7NPJPEVn2QdSH2Qlk_iJWUupA8cX2p6zU6uMgH2njiz7TTYWBdDfw

// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzE2MzYsImV4cCI6MTc0MDYzMTkzNiwidXNlcm5hbWUiOiJhZG1pbiJ9.NF5QP6X9lxTU762hs6stWWQ2EsxVKxGQK1Y9LSaHdxrVKdvaFqc2pGyTrVf5RELXsfEc_u6bJR4_QXAHw9zMnXf-v1igly_fI3Nwr1l5iRHdHYPTxKZvfXl3jW6bwU1julX-LhkvrWNDYuGkECOIiiNomWbfqbef7inXxHYfD4-rR0mG_P80GF012RQLUWyAGqt2tf1ZiHQvKqbwIsuAar_lpGz6QWe4F4M1Vk8snlVwyu-Xk-H910n6ytaIOE-_RHSwuOr-gu--kJns9ZfPMoUgDCQO4rm9z7NPJPEVn2QdSH2Qlk_iJWUupA8cX2p6zU6uMgH2njiz7TTYWBdDfw

// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDA2MzIyMDksImV4cCI6MTc0MDYzMjUwOSwidXNlcm5hbWUiOiJhZG1pbiJ9.Qi0QQ7JoMw2unW5OqbY_J55iYfk2KiIMypXdDJ9ZRXtmmq7PHi3ikJtOxzbindltjhQ6WTsrkjxxDouFrZHroOPw1kPi-m61UGH-Zq99HxjIq9q-vKxnw4uR0fKieXp3PMDPPCsSTmV9vjs1Y7D-2-K1OUDyAlGBV7ClWPaquRK939fAyATKE2lYMzZ1RWlRWh-roD0bztExppNnnk4lIZJZzSpDoAC4D_akGJaFP-NOpdeiU6EpOPpCqD2M6OPW2C3KaPz-i52h7ywdJVUjNi-ZZYe8K0dZVALZX5hX19h_Z31dROcaaZT-2KPdxHP7_faybGdh-vIBsS1tLPwPJg